using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Net.Sockets;
using System.Threading;
using System.Text;

///////////////////////////
// Ch347s                //
// Player selection menu //
// god1 = G+O+D+1        //
// god2 = G+O+D+2        //
///////////////////////////


// Dit is een test dionas
// Aanpassing azad

namespace RaceGame2013
{
    /// <summary>d
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        // Declaring GameState
        enum GameState
        {
            MainMenu,
            Options,
            SelectCar,
            SelectTrack,
            Playing,
            GameOver,
        }
        //When is loading is in MainMenu
        GameState CurrentGameState = GameState.MainMenu;

        // Screen Adjustments
        int screenWidth = 1280, screenHeight = 800;

        // Game Buttons:
        CButton buttonLetsGo; // GameButtonLetsGO
        CButton buttonSelectTrack; // Select track button

        CButton buttonPlayer1; // OnePlayerButton
        CButton buttonPlayer1Taxi; //Taxi button
        CButton buttonPlayer1Bus; // Bus button
        CButton buttonPlayer1BMW; // BMW button

        CButton buttonPlayer2; // buttonPlayer2
        CButton buttonPlayer2Taxi; //Taxi button
        CButton buttonPlayer2Bus; // Bus button
        CButton buttonPlayer2BMW; // BMW button

        CButton buttonSelectTrack1;
        CButton buttonSelectTrack2;


        // Players
        string player1Car;
        string player2Car;

        // Cheat var
        Boolean player1GodMode = false;
        Boolean player2GodMode = false;

        // check if players are ready
        Boolean player1Ready = false;
        Boolean player2Ready = false;


        // Track
        Track track;
        // Selected track
        string strTrack;

        // voertuig
        Voertuig voertuig1;
        Voertuig voertuig2;

        // ScoreBoard
        ScoreBoard scoreBoard1;
        ScoreBoard scoreBoard2;

        // HealthPowerUP
        HealthPowerUp healthPowerUp;
        Boolean hasDroppedHealthPowerUp = false;
        // SpeedPowerUP
        SpeedPowerUp speedPowerUp;
        Boolean hasDroppedSpeedPowerUp = false;

        // GameMenu sound
        Song gameMenuSound;


        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);

            // Change the screen width and height
            graphics.PreferredBackBufferWidth = 1280;
            graphics.PreferredBackBufferHeight = 800;

            // Apply the new Changes
            graphics.ApplyChanges();

            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // Track
            track = new Track();

            // Load the game sound and start it
            gameMenuSound = Content.Load<Song>("Sound/MenuSound");
            MediaPlayer.IsRepeating = true;
            MediaPlayer.Play(gameMenuSound);

            // Player 1: Create new voertuig based on the choice of the menu
            switch(player1Car)
            {
                case "taxi":
                    voertuig1 = new Taxi(Content, graphics, spriteBatch, track, new Vector2(900, 460), 1);
                    break;
                case "bmw":
                    voertuig1 = new BMW(Content, graphics, spriteBatch, track, new Vector2(900, 460), 1);
                    break;
                case "bus":
                    voertuig1 = new Bus(Content, graphics, spriteBatch, track, new Vector2(900, 460), 1);
                    break;
                default:
                    voertuig1 = new BMW(Content, graphics, spriteBatch, track, new Vector2(900, 460), 1);
                    break;
            }

            // Player 2: Create new voertuig based on the choice of the menu
            switch (player2Car)
            {
                case "taxi":
                    voertuig2 = new Taxi(Content, graphics, spriteBatch, track, new Vector2(900, 530), 2);
                    break;
                case "bmw":
                    voertuig2 = new BMW(Content, graphics, spriteBatch, track, new Vector2(900, 530), 2);
                    break;
                case "bus":
                    voertuig2 = new Bus(Content, graphics, spriteBatch, track, new Vector2(900, 530), 2);
                    break;
                default:
                    voertuig2 = new Taxi(Content, graphics, spriteBatch, track, new Vector2(900, 530), 2);
                    break;
            }

            // Create new ScoreBoards for each car
            scoreBoard1 = new ScoreBoard(Content, graphics, spriteBatch, voertuig1);
            scoreBoard2 = new ScoreBoard(Content, graphics, spriteBatch, voertuig2);

            // HealthPowerUp object 
            Random rd = new Random(DateTime.Now.Millisecond);
            healthPowerUp = new HealthPowerUp(Content, spriteBatch, new Vector2(rd.Next(50,1280), rd.Next(50,800)), 100);

            // SpeedPowerup object
            speedPowerUp = new SpeedPowerUp(Content, spriteBatch, new Vector2(rd.Next(50, 1280), rd.Next(50, 800)), 10);


            // Cheat check player 1
            if (player1GodMode)
            {
                voertuig1.health = 100000;
                voertuig1.gas = 100000;
                voertuig1.carSpeed = 10;
            }

            // Cheat check player 1
            if (player2GodMode)
            {
                voertuig2.health = 100000;
                voertuig2.gas = 100000;
                voertuig2.carSpeed = 10;
            }

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Load the car 
            voertuig1.LoadContent();
            voertuig2.LoadContent();

            // Load the scoreboard for each car
            scoreBoard1.LoadContent();
            scoreBoard2.LoadContent();

            // Track
            track.LoadContent(Content, graphics, voertuig1, "Tracks/RacingMapOnderlaag", "Tracks/RacingMap");
            //track.LoadContent(Content, graphics, voertuig1, "Tracks/Onderlaag", "Tracks/Map.Bovenlaag");


            // For Testing the game:
            //graphics.IsFullScreen = true;
            graphics.ApplyChanges();
            IsMouseVisible = true;

            // Lets plays (Start Game Button)
            buttonLetsGo = new CButton(Content.Load<Texture2D>("Menu/GameButtonLetsGO"),graphics.GraphicsDevice);
            buttonLetsGo.setPosition(new Vector2(screenWidth / 2, screenHeight / 2));

            // Game Button2 for One Player
            buttonPlayer1 = new CButton(Content.Load<Texture2D>("Menu/OnePlayerButton1"), graphics.GraphicsDevice);
            buttonPlayer1.setPosition(new Vector2(800, 700));

            // Game Button3 for Two Players
            buttonPlayer2 = new CButton(Content.Load<Texture2D>("Menu/TwoPlayerButton"), graphics.GraphicsDevice);
            buttonPlayer2.setPosition(new Vector2(95, 700));

            // Load textures for car selection buttons
            Texture2D texturebuttonTaxi = Content.Load<Texture2D>("Menu/TaxiButton");
            Texture2D texturebuttonBus = Content.Load<Texture2D>("Menu/BusButton");
            Texture2D texturebuttonBMW = Content.Load<Texture2D>("Menu/BMWButton");

            // Game Button4 for selection track
            buttonSelectTrack1 = new CButton(Content.Load<Texture2D>("Menu/TwoPlayerButton"), graphics.GraphicsDevice);
            buttonSelectTrack1.setPosition(new Vector2(95, 700));
            buttonSelectTrack2 = new CButton(Content.Load<Texture2D>("Menu/TwoPlayerButton"), graphics.GraphicsDevice);
            buttonSelectTrack2.setPosition(new Vector2(95, 700));

            ////////////////////////// Player 2 car selection buttons Menu ////////////////////////////////////////
            // Taxi
            buttonPlayer1Taxi = new CButton(texturebuttonTaxi, graphics.GraphicsDevice, texturebuttonTaxi.Width, texturebuttonTaxi.Height);
            buttonPlayer1Taxi.setPosition(new Vector2(220, 100));

            //  Bus
            buttonPlayer1Bus = new CButton(texturebuttonBus, graphics.GraphicsDevice, texturebuttonBus.Width, texturebuttonBus.Height);
            buttonPlayer1Bus.setPosition(new Vector2(220, 300));

            // BMW
            buttonPlayer1BMW = new CButton(texturebuttonBMW, graphics.GraphicsDevice, texturebuttonBMW.Width, texturebuttonBMW.Height);
            buttonPlayer1BMW.setPosition(new Vector2(220, 500));

            ////////////////////////// Player 2 car selection buttons Menu ////////////////////////////////////////

            // Taxi
            buttonPlayer2Taxi = new CButton(texturebuttonTaxi, graphics.GraphicsDevice, texturebuttonTaxi.Width, texturebuttonTaxi.Height);
            buttonPlayer2Taxi.setPosition(new Vector2(860, 100));

            //  Bus
            buttonPlayer2Bus = new CButton(texturebuttonBus, graphics.GraphicsDevice, texturebuttonBus.Width, texturebuttonBus.Height);
            buttonPlayer2Bus.setPosition(new Vector2(860, 300));

            // BMW
            buttonPlayer2BMW = new CButton(texturebuttonBMW, graphics.GraphicsDevice, texturebuttonBMW.Width, texturebuttonBMW.Height);
            buttonPlayer2BMW.setPosition(new Vector2(860, 500));


            // Game Button7 for Selecting Track. After this the game wil start
            Texture2D textureSelectTrack = Content.Load<Texture2D>("Menu/Button3");
            buttonSelectTrack = new CButton(textureSelectTrack, graphics.GraphicsDevice);
            buttonSelectTrack.setPosition(new Vector2(screenWidth / 2 , screenHeight / 2));

            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // Check if the game is still valid to run and if nobody has died 
            if ((voertuig1.health <= 0) || (voertuig2.health <= 0) || (voertuig1.laps > 10) || (voertuig2.laps >= 10))
            {
                CurrentGameState = GameState.GameOver;
            }

            // Get the mousestate for input
            MouseState mouse = Mouse.GetState();

            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            switch (CurrentGameState)
            {
                case GameState.MainMenu:
                    if (buttonLetsGo.isClicked == true) CurrentGameState = GameState.Options;
                    buttonLetsGo.Update(mouse);
                    break;

                case GameState.Options:
                    // Click event for buttonPlayer1
                    if (buttonPlayer1.isClicked == true)
                    {
                        CurrentGameState = GameState.SelectCar;
                        break;
                    }
                    buttonPlayer1.Update(mouse);

                    // Click event for buttonPlayer2
                    if (buttonPlayer2.isClicked == true)
                    {
                        CurrentGameState = GameState.SelectCar;
                    }

                    buttonPlayer2.Update(mouse);
                    break;

                case GameState.SelectCar:
                    // Check if players are ready
                    if ((player1Ready) && (player2Ready))
                    {
                        // Then change the to second screen to change the track
                        CurrentGameState = GameState.SelectTrack;

                       // Load the new selection
                        this.Initialize();
                        this.LoadContent();
                    }

                    // Player one event handlers
                    if (buttonPlayer1Taxi.isClicked == true)
                    {
                        // Has selected a car
                        player1Car = "taxi";
                        player1Ready = true;
                    }
                    if (buttonPlayer1Bus.isClicked == true)
                    {
                        // Has selected a car
                        player1Car = "bus";
                        player1Ready = true;
                    }
                    if (buttonPlayer1BMW.isClicked == true)
                    {
                        // Has selected a car
                        player1Car = "bmw";
                        player1Ready = true;
                    }

                    // Player one buttons
                    switch(player1Car)
                    {
                        case "taxi":
                            buttonPlayer1Taxi.Update(mouse);
                            break;
                        case "bus": 
                            buttonPlayer1Bus.Update(mouse);
                            break;
                        case "bmw": 
                            buttonPlayer1BMW.Update(mouse);
                            break;
                        default:
                            buttonPlayer1Taxi.Update(mouse);
                            buttonPlayer1Bus.Update(mouse);
                            buttonPlayer1BMW.Update(mouse);
                            break;
                    }
                    // Player one event handlers
                    if (buttonPlayer2Taxi.isClicked == true)
                    {
                        // Has selected a car
                        player2Car = "taxi";
                        player2Ready = true;
                    }
                    if (buttonPlayer2Bus.isClicked == true)
                    {
                        // Has selected a car
                        player2Car = "bus";
                        player2Ready = true;
                    }
                    if (buttonPlayer2BMW.isClicked == true)
                    {
                        // Has selected a car
                        player2Car = "bmw";
                        player2Ready = true;
                    }

                    // Player one buttons
                    switch (player2Car)
                    {
                        case "taxi":
                            buttonPlayer2Taxi.Update(mouse);
                            break;
                        case "bus":
                            buttonPlayer2Bus.Update(mouse);
                            break;
                        case "bmw":
                            buttonPlayer2BMW.Update(mouse);
                            break;
                        default:
                            buttonPlayer2Taxi.Update(mouse);
                            buttonPlayer2Bus.Update(mouse);
                            buttonPlayer2BMW.Update(mouse);
                            break;
                    }
                    break;

                case GameState.SelectTrack:
                    if (buttonSelectTrack.isClicked == true)
                    {
                        CurrentGameState = GameState.Playing;
                    }
                    buttonSelectTrack.Update(mouse);
                    break;

                case GameState.Playing:

                    break;
            }

            // Car update for the control etc
            voertuig1.Update(gameTime);
            voertuig2.Update(gameTime);

            ///////////////////////////////
            //  Game Colisions
            //

            // Check if the two car hit eacht other
            if (voertuig1.voertuigCollisionBox.Intersects(voertuig2.voertuigCollisionBox) || voertuig2.voertuigCollisionBox.Intersects(voertuig1.voertuigCollisionBox))
            {
                // Both cars hit each other so increment by the damage value of the car's
                voertuig1.health = voertuig1.health-voertuig2.damage;
                voertuig2.health -= voertuig1.damage;

                // If hit then get the set the old position of the car as the position
                voertuig1.Position = voertuig1.oldPosition;
                voertuig2.Position = voertuig2.oldPosition;
            }
            else {
                // Save the position before a collision to the car
                voertuig1.oldPosition = voertuig1.Position;
                voertuig2.oldPosition = voertuig2.Position;
            }

            // Check if player one's cars is hit by a bullet
            foreach (Kogel kogel in voertuig1.kogels)
            {
                if (kogel.bulletCollisionBox.Intersects(voertuig2.voertuigCollisionBox) || voertuig2.voertuigCollisionBox.Intersects(kogel.bulletCollisionBox))
                {
                    Console.WriteLine("The car was hit by a bullet! {0}", voertuig2.player);
                    kogel.Kill();
                    voertuig2.health -= 1;
                }
            }

            // Check if player two's cars is hit by a bullet
            foreach (Kogel kogel in voertuig2.kogels)
            {
                if (kogel.bulletCollisionBox.Intersects(voertuig1.voertuigCollisionBox) || voertuig1.voertuigCollisionBox.Intersects(kogel.bulletCollisionBox))
                {
                    Console.WriteLine("The car was hit by a bullet! {0}", voertuig1.player);
                    kogel.Kill();
                    voertuig1.health -= 0.2f;
                }
            }


            // BEGING POWERUPS
            // Check if the player one's cars is driving over a health object
            if ((voertuig1.voertuigCollisionBox.Intersects(healthPowerUp.healthPowerUpColisionBox)) || (healthPowerUp.healthPowerUpColisionBox.Intersects(voertuig1.voertuigCollisionBox)))
            { 
                // Make his health the health its driving over
                voertuig1.health = healthPowerUp.health;
            }

            // Check if the player two's cars is driving over a health object
            if ((voertuig2.voertuigCollisionBox.Intersects(healthPowerUp.healthPowerUpColisionBox)) || (healthPowerUp.healthPowerUpColisionBox.Intersects(voertuig2.voertuigCollisionBox)))
            {
                // Make his health the health its driving over
                voertuig2.health = healthPowerUp.health;
            }

            if ((voertuig1.voertuigCollisionBox.Intersects(speedPowerUp.speedPowerUpColisionBox)) || (speedPowerUp.speedPowerUpColisionBox.Intersects(voertuig1.voertuigCollisionBox)))
            {
                // Make his health the health its driving over
                voertuig1.speed = speedPowerUp.speed;
            }

            // Check if the player two's cars is driving over a health object
            if ((voertuig2.voertuigCollisionBox.Intersects(speedPowerUp.speedPowerUpColisionBox)) || (speedPowerUp.speedPowerUpColisionBox.Intersects(voertuig2.voertuigCollisionBox)))
            {
                // Make his health the health its driving over
                voertuig2.speed = speedPowerUp.speed;
            }
            // END POWERUPS

            
            if (((voertuig1.laps + 1) % 2 == 0) && ((voertuig1.laps + 1) % 2 == 0) && hasDroppedHealthPowerUp == false)
            {
                // Making a true random value
                Random rd = new Random(DateTime.Now.Millisecond * gameTime.ElapsedGameTime.Milliseconds);
                healthPowerUp = new HealthPowerUp(Content, spriteBatch, new Vector2(rd.Next(100, 500), rd.Next(100, 500)), 200);
                hasDroppedHealthPowerUp = true;
            }
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here
            // Beging 
            spriteBatch.Begin();
            switch (CurrentGameState)
            {
                case GameState.MainMenu:
                    spriteBatch.Draw(Content.Load<Texture2D>("Menu/MainMenu"), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
                    buttonLetsGo.Draw(spriteBatch);
                     break;

                case GameState.Options:
                    spriteBatch.Draw(Content.Load<Texture2D>("Menu/Options"), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
                    buttonPlayer1.Draw(spriteBatch);
                    buttonPlayer2.Draw(spriteBatch);

                    // CHEATS ;)
                    KeyboardState keyBoard = Keyboard.GetState();

                    // GodMode Player1
                    if (keyBoard.IsKeyDown(Keys.G) && keyBoard.IsKeyDown(Keys.O) && keyBoard.IsKeyDown(Keys.D) && keyBoard.IsKeyDown(Keys.NumPad1))
                    {
                        SoundEffect gundShot = Content.Load<SoundEffect>("Sound/Shot");
                        gundShot.Play();
                        player1GodMode = true;
                    }


                    // GodMode Player1
                    if (keyBoard.IsKeyDown(Keys.G) && keyBoard.IsKeyDown(Keys.O) && keyBoard.IsKeyDown(Keys.D) && keyBoard.IsKeyDown(Keys.NumPad2))
                    {
                        SoundEffect gundShot = Content.Load<SoundEffect>("Sound/Shot");
                        gundShot.Play();
                        player2GodMode = true;
                    }
                    break;

                case GameState.SelectCar:
                    spriteBatch.Draw(Content.Load<Texture2D>("Menu/SelectCarBackGround"), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
                    switch (player1Car)
                    {
                        case "taxi":
                            buttonPlayer1Taxi.Draw(spriteBatch);
                            break;
                        case "bus":
                            buttonPlayer1Bus.Draw(spriteBatch);
                            break;
                        case "bmw":
                            buttonPlayer1BMW.Draw(spriteBatch);
                            break;
                        default:
                            buttonPlayer1Taxi.Draw(spriteBatch);
                            buttonPlayer1Bus.Draw(spriteBatch);
                            buttonPlayer1BMW.Draw(spriteBatch);
                            break;
                    }
                    // Draw Player two
                    switch (player2Car)
                    {
                        case "taxi":
                            buttonPlayer2Taxi.Draw(spriteBatch);
                            break;
                        case "bus":
                            buttonPlayer2Bus.Draw(spriteBatch);
                            break;
                        case "bmw":
                            buttonPlayer2BMW.Draw(spriteBatch);
                            break;
                        default:
                            buttonPlayer2Taxi.Draw(spriteBatch);
                            buttonPlayer2Bus.Draw(spriteBatch);
                            buttonPlayer2BMW.Draw(spriteBatch);
                            break;
                    }
                    break;

                case GameState.SelectTrack:
                    spriteBatch.Draw(Content.Load<Texture2D>("Menu/Options"), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
                    buttonSelectTrack.Draw(spriteBatch);
                    break;

                case GameState.Playing:
                    // Begin Spel logic
                    // Draw the track overlay
                    track.Draw(spriteBatch);

                    // Draw the healthPoweUp object
                    healthPowerUp.Draw();
                    // Draw the speedPowerUp object
                    speedPowerUp.Draw();

                    // Drawing our car
                    voertuig1.Draw(spriteBatch);
                    voertuig2.Draw(spriteBatch);

                    scoreBoard1.Draw();
                    scoreBoard2.Draw();

                    // End Game Logic
                    break;
                // 
                case GameState.GameOver:
                    spriteBatch.Draw(Content.Load<Texture2D>("Menu/GameOver"), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);

                     // Position of the string
                    Vector2 pos = new Vector2(screenWidth / 2, screenHeight / 2);

                    // Making a new stringbuilder
                    StringBuilder strScoreBoard = new StringBuilder();

                    if((voertuig2.health < voertuig1.health) || (voertuig1.laps > voertuig2.laps))
                    {
                        strScoreBoard.Append("Player " + voertuig1.player.ToString() + " Wins\n");
                    }
                    
                    if ((voertuig1.health < voertuig2.health) || (voertuig2.laps > voertuig1.laps))
                    {
                        strScoreBoard.Append("Player " + voertuig2.player.ToString() + " Wins\n");
                    }

                    // Fonts
                    SpriteFont font = Content.Load<SpriteFont>("FontGameOver");

                    // Draw the string
                    spriteBatch.DrawString(font, strScoreBoard, pos, Color.Black);
                    break;
            }  

            // End
            spriteBatch.End();
            base.Draw(gameTime);
        }

      
    }
}